#include <iostream>
#include <fstream>
#include <array>
#include <cstdint>

template<size_t N>
void print_array(const std::array<uint8_t, N>& arr, const std::string& name = "")
{
    if (!name.empty()) {
        std::cout << name << ": ";
    }
    std::cout << "[";
    for (size_t i = 0; i < N; ++i) {
        std::cout << static_cast<int>(arr[i]);
        if (i != N - 1) std::cout << ", ";
    }
    std::cout << "]" << std::endl;
}
const char* read_wave_type(std::ifstream& file,std::streamoff offest)
{
	file.seekg(offest);
	uint8_t byte;
	file.read(reinterpret_cast<char*>(&byte), sizeof(byte));
	switch(byte)
	{
		case 0:
			return "saw";
		case 3:
			return "wave2";
		case 2:
			return "sin";
		case 1:
			return "square";
		default:
			return "unknown";
	}
	file.close();
}
const char* read_lfo_type(std::ifstream& file,std::streamoff offest)
{
	uint8_t byte;
	file.seekg(offest);
	file.read(reinterpret_cast<char*>(&byte), sizeof(byte));
	switch(byte)
	{
		case 0:
			return "sin";
		case 1:
			return "square";
		default:
			return "unknown";
	}
}
const char* read_lfo_target(std::ifstream& file,std::streamoff offest)
{
	uint8_t byte;
	file.seekg(offest);
	file.read(reinterpret_cast<char*>(&byte), sizeof(byte));
	switch(byte)
	{
		case 0:
			return "osc1/2";
		case 1:
			return "reso";
		case 2:
			return "cutoff";
		default:
			return "unknown";
	}
}
uint16_t read_master(std::ifstream& file,std::streamoff offest)
{
	file.seekg(offest);
	uint16_t byte;
	file.read(reinterpret_cast<char*>(&byte), sizeof(byte));
	return byte;
}

/*float read_adsr_a(std::ifstream& file,std:streamoff offest)
{
	file.seekg(offest);

	return read(offest);
}

*/
// 范围 hex:01 00 - 00 40
float read_filter_cutoff(std::ifstream &file,std::streamoff offest)
{
	const uint16_t min = 1;
	const uint16_t max = 0x4000;
	file.seekg(offest);
	uint16_t value;
	file.read(reinterpret_cast<char*>(&value), sizeof(value));
	return (static_cast<float>(value-min)/(max-min));
}
float read_filter_envamt(std::ifstream &file,std::streamoff offest)
{
	uint16_t value;
	file.seekg(offest);
	file.read(reinterpret_cast<char*>(&value), sizeof(value));
	return (static_cast<float>(value));
}

float read_filter_reso(std::ifstream &file,std::streamoff offest)
{
	uint16_t value;
	file.seekg(offest);
	file.read(reinterpret_cast<char*>(&value), sizeof(value));
	return  (static_cast<float>(value));
}
const char* read_filter_type(std::ifstream &file,std::streamoff offest)
{
	uint8_t byte;
	file.seekg(offest);
	file.read(reinterpret_cast<char*>(&byte), sizeof(byte));
	switch(byte)
	{
		case 0:
			return "lo12";
		case 1:
			return "lo24";
		case 2:
			return "hi12";
		case 3:
			return "Band";
		case 4:
			return "ByPass";
		default:
			return "unknown";
	}
}
int read_bpm(std::ifstream& file,std::streamoff offest)
{
	file.seekg(offest);
	uint8_t byte;
	file.read(reinterpret_cast<char*>(&byte), sizeof(byte));
	return static_cast<int>(byte);
}
// 读取音序器的音高数据
std::array<uint8_t,16> read_note(std::ifstream &file,std::streamoff offest)
{
	//uint8_t notes[16];
	std::array<uint8_t,16> notes{};
	file.seekg(offest);
	for (int i = 0; i < 16; i++)
	{
		uint8_t byte;
		file.read(reinterpret_cast<char*>(&byte), sizeof(byte));
		notes[i] = byte;
	}
	return notes;
}
std::array<uint8_t,16> read_note_on_off(std::ifstream &file,std::streamoff offest)
{
	std::array<uint8_t,16> onoff{};
	for(int i=0;i<16;i++)
	{
		uint8_t byte;
		file.read(reinterpret_cast<char*>(&byte), sizeof(byte));
		onoff[i] = byte;
	}
	return onoff;
}
std::array<uint8_t,16> read_note_slide(std::ifstream &file,std::streamoff offest)
{
	std::array<uint8_t,16> slide{};
	for(int i=0;i<16;i++)
	{
		uint16_t byte;
		file.read(reinterpret_cast<char*>(&byte), sizeof(byte));
		slide[i] = byte;
	}
	return slide;
}
int main(int argc,char** argv)
{
	char *filename = argv[1];
	std::ifstream file(filename,std::ios::binary);

	const char* osc1_wave = read_wave_type(file,0x00000026);
	const char* osc2_wave = read_wave_type(file,0x00000028);
	int bpm = read_bpm(file,0x000008F2);
	const char* lfo_type = read_lfo_type(file,0x000008A8);
	const char* lfo_target = read_lfo_target(file,0x000008A6);
	uint16_t master_vol = read_master(file,0x00000012);
	const char* filter_type = read_filter_type(file,0x0000088C);
	float cutoff = read_filter_cutoff(file,0x0000088F)*20000;
	float envamt = read_filter_envamt(file,0x00000896);
	float reso = read_filter_reso(file,0x0892);
	auto notes = read_note(file,0x000008F6);
	auto on_off = read_note_on_off(file,0x00000906);
	auto slide = read_note_slide(file,0x00000916);
	file.close();
	// 目前不清楚adsr的每个bit是什么意思
	//float asdr_a = read_adsr_a(0x000008CE,7);
	/*float adsr_d = read_adsr_d(0x000008D6,3);
	float adsr_s = read_asdr_s(0x000008DA,3);
	float adsr_r = read_adsr_r(0x000008DE,7)
	*/
	std::cout << "Osc1 Wave: " << osc1_wave << std::endl;
	std::cout << "Osc2 Wave: " << osc2_wave << std::endl;
	std::cout << "LFO Type: " << lfo_type << std::endl;	
	std::cout << "LFO Target: " << lfo_target << std::endl;
	std::cout << "Filter Type: " << filter_type << std::endl;
	std::cout << "Cutoff: " << cutoff << std::endl;
	std::cout << "Filter Env Amount: " << envamt << std::endl;
	std::cout << "Resonance: " << reso << std::endl;
	print_array(notes,"Notes");
	print_array(on_off,"Note On/Off");
	print_array(slide,"Note Slide");
	/*std::cout << "notes: " << notes << std::endl;
	std::cout << "noteOnOff: " << on_off << std::endl;
	std::cout << "noteSlide: " << slide << std::endl;*/
	std::cout << "BPM: " << bpm << std::endl;
	std::cout << "Master Volume: " << master_vol << std::endl;
	return 0;
}